﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NSuggest.Jsonp.Core;

namespace NSuggest.Example.Cats
{
	/// <summary>
	/// An example of how to use JsonpEngine inside a IHttpHandler.
	/// </summary>
	public class CatsJsonpService : IHttpHandler
	{

		public void ProcessRequest(HttpContext context)
		{
			var catFinder = new CatSearcher();
			var engine = new JsonpEngine(catFinder.SearchForCats);

			// (Optional) subscribe to events
			engine.ErrorEvent += ((obj, e) => Console.WriteLine("An error occured. The HTTP status code was: " + e.HttpStatusCode));
			engine.SuccessEvent += ((obj, e) => Console.WriteLine("Great success occured. Cats found was: " + ((IEnumerable<Cat>)e.Result).Count()));
			engine.CompletedEvent += ((obj, e) => Console.WriteLine("It's all over"));

			// Run engine with context
			engine.Execute(context);
		}

		public bool IsReusable
		{
			get { return false; }
		}
	}

	public class CatSearcher
	{
		private readonly Cat[] _cats = new[]
								 {
									 new Cat("Tiger", "Panthera Tigris"),
									 new Cat("Lion", "Panthera Leo"),
									 new Cat("Jaguar", "Panthera Onca"),
									 new Cat("Leopard", "Panthera Pardus"),
									 new Cat("Snow Leopard", "Panthera Uncia"),
									 new Cat("Mountain Lion", "Puma Concolor"),
									 new Cat("Cheetah", "Acinonyx Jubatus"),
									 new Cat("Lynx", "Lynx Lynx"),
								 };

		public IEnumerable<Cat> SearchForCats(HttpContext context)
		{
			var query = context.Request.QueryString["q"].ToLower();
			var tokens = query.Split(' ').Where(x => !string.IsNullOrEmpty(x));
			//var cats = _cats.Where(cat => MatchesAllTokens(cat, tokens));
			var cats = _cats
				.Select(cat => new {Cat = cat, Rank = Rank(cat, tokens)})
				.Where(x => x.Rank > 0)
				.OrderByDescending(x => x.Rank)
				.Select(x => x.Cat);
			return cats.ToList();
		}

		private static bool MatchesAllTokens(Cat cat, IEnumerable<string> tokens)
		{
			return !tokens.Any(token => !cat.EnglishName.ToLower().Contains(token) && !cat.LatinName.ToLower().Contains(token));

		}

		private static int Rank(Cat cat, IEnumerable<string> tokens)
		{
			return tokens.Count(
					token => cat.EnglishName.ToLower().Contains(token) || cat.LatinName.ToLower().Contains(token));
		}
	}
}